import time
from machine import Pin
from machine import PWM
import random
import utime

# 蜂鸣器引脚（无源蜂鸣器）
buzzer = PWM(Pin(14), freq=440, duty=0)  # 初始频率为 440 Hz（A4），占空比为 0（静音）

# 音符频率表（单位：Hz）
notes = {
    "C4": 262, "D4": 294, "E4": 330, "F4": 349, "G4": 392,
    "A4": 440, "B4": 494, "C5": 523, "D5": 587, "E5": 659,
    "F5": 698, "G5": 784, "A5": 880, "B5": 988
}

# 音效模式
sound_patterns = {
    "start_game": [("E5", 150), ("C5", 150)],          # 游戏开始：简短的两个音符
    "row_clear": [("G4", 100), ("E4", 50), ("C4", 50)],  # 行消除得分：有节奏的三声
    # 其他音效模式可以根据需要添加
}

def play_sound(state):
    """根据状态播放蜂鸣器声音"""
    if state in sound_patterns:
        for note, duration in sound_patterns[state]:
            if note in notes:  # 检查音符是否有效
                buzzer.freq(notes[note])  # 设置频率
                buzzer.duty(512)  # 设置占空比（50%）
                utime.sleep_ms(duration)  # 持续发声
                buzzer.duty(0)  # 停止发声
                utime.sleep_ms(50)  # 音符间隔

def run(ed, k_u, k_d, k_l, k_r, k_a, k_b, dp):
    CELL_SIZE = 8  # 方块大小
    C = 12  # 横向格子数
    R = 16  # 纵向格子数
    WIDTH = C * CELL_SIZE  # 屏幕宽度
    HEIGHT = R * CELL_SIZE  # 屏幕高度
    OFFSET_X = (dp.width - WIDTH) // 2  # 屏幕显示偏移
    OFFSET_Y = (dp.height - HEIGHT) // 2

    COLORS = {
        "O": 0x001F,   # 蓝色
        "S": 0xF800,   # 红色
        "T": 0xFFE0,   # 黄色
        "I": 0x07E0,   # 绿色
        "L": 0x780F,   # 紫色
        "J": 0xFD20,   # 橙色
        "Z": 0x07FF,   # 青色
        "bg": 0x0000   # 黑色背景
    }

    SHAPES = {
        "O": [(-1, -1), (0, -1), (-1, 0), (0, 0)],
        "S": [(-1, 0), (0, 0), (0, -1), (1, -1)],
        "T": [(-1, 0), (0, 0), (0, -1), (1, 0)],
        "I": [(0, 1), (0, 0), (0, -1), (0, -2)],
        "L": [(-1, 0), (0, 0), (-1, -1), (-1, -2)],
        "J": [(-1, 0), (0, 0), (0, -1), (0, -2)],
        "Z": [(-1, -1), (0, -1), (0, 0), (1, 0)],
    }

    block_list = [['' for _ in range(C)] for _ in range(R)]  # 玩家区域数组
    current_block = None  # 当前方块
    score = 0  # 得分
    paused = False  # 暂停状态（已删除暂停功能）

    key_left = Pin(27, Pin.IN, Pin.PULL_UP)  # 左键
    key_right = Pin(35, Pin.IN, Pin.PULL_UP)  # 右键
    key_rotate = Pin(2, Pin.IN, Pin.PULL_UP)  # 上键（旋转）
    key_down = Pin(13, Pin.IN, Pin.PULL_UP)  # 下键（加速下降）
    key_pause = Pin(34, Pin.IN, Pin.PULL_UP)  # A 键（暂停，已删除）

    def draw_borders():
        """绘制俄罗斯方块的游戏边界"""
        border_color = 0xFFFF  # 白色
        ed.fill_rect(OFFSET_X, OFFSET_Y, 1, HEIGHT, border_color)  # 左边界
        ed.fill_rect(OFFSET_X + WIDTH - 1, OFFSET_Y, 1, HEIGHT, border_color)  # 右边界

    def check_move(block, direction):
        """检查方块是否可以移动"""
        cc, cr = block['cr']
        for cell in block['cell_list']:
            c = cc + cell[0] + direction[0]
            r = cr + cell[1] + direction[1]
            if c < 0 or c >= C or r >= R or (r >= 0 and block_list[r][c]):
                return False
        return True

    def draw_cell(c, r, color):
        """绘制一个方块"""
        x = c * CELL_SIZE + OFFSET_X
        y = r * CELL_SIZE + OFFSET_Y
        ed.fill_rect(x, y, CELL_SIZE, CELL_SIZE, color)

    def draw_block(block, clear=False):
        """绘制方块"""
        color = COLORS['bg'] if clear else COLORS[block['kind']]
        for cell in block['cell_list']:
            cc, cr = block['cr']
            c = cc + cell[0]
            r = cr + cell[1]
            if 0 <= c < C and 0 <= r < R:
                draw_cell(c, r, color)

    def new_block():
        """生成新的方块"""
        kind = random.choice(list(SHAPES.keys()))
        return {
            'kind': kind,
            'cell_list': SHAPES[kind],
            'cr': [C // 2, 0]
        }

    def debounce(pin):
        """按键消抖"""
        start_time = time.ticks_ms()
        while time.ticks_diff(time.ticks_ms(), start_time) < 20:
            if pin.value() != 0:
                return False
        return True

    def game_loop():
        """俄罗斯方块游戏主循环"""
        nonlocal current_block, score

        draw_borders()
        ed.fill_rect(OFFSET_X, OFFSET_Y, WIDTH, CELL_SIZE, COLORS['bg'])

        while True:
            # 键盘事件处理
            if debounce(key_left):
                if current_block and check_move(current_block, (-1, 0)):
                    draw_block(current_block, clear=True)
                    current_block['cr'][0] -= 1
                    draw_block(current_block)
            if debounce(key_right):
                if current_block and check_move(current_block, (1, 0)):
                    draw_block(current_block, clear=True)
                    current_block['cr'][0] += 1
                    draw_block(current_block)
            if debounce(key_rotate):
                if current_block:
                    rotated = [[cell[1], -cell[0]] for cell in current_block['cell_list']]
                    rotated_block = {
                        'kind': current_block['kind'],
                        'cell_list': rotated,
                        'cr': current_block['cr']
                    }
                    if check_move(rotated_block, (0, 0)):
                        draw_block(current_block, clear=True)
                        current_block = rotated_block
                        draw_block(current_block)
            if debounce(key_down):
                if current_block and check_move(current_block, (0, 1)):
                    draw_block(current_block, clear=True)
                    current_block['cr'][1] += 1
                    draw_block(current_block)

            # 检查是否需要生成新方块
            if current_block is None:
                current_block = new_block()
                if not check_move(current_block, (0, 0)):
                    ed.text("GAME OVER", 30 + OFFSET_X, 60 + OFFSET_Y, 0xF800)  # 显示游戏结束
                    play_sound("game_over")  # 游戏结束播放音效
                    return
                draw_block(current_block)
            else:
                # 方块下落
                if check_move(current_block, (0, 1)):
                    draw_block(current_block, clear=True)
                    current_block['cr'][1] += 1
                    draw_block(current_block)
                else:
                    # 锁定方块
                    for cell in current_block['cell_list']:
                        cc, cr = current_block['cr']
                        c = cc + cell[0]
                        r = cr + cell[1]
                        if 0 <= c < C and 0 <= r < R:
                            block_list[r][c] = current_block['kind']
                    current_block = None

                    # 检测消除整行
                    full_rows = [i for i, row in enumerate(block_list) if all(row)]
                    if full_rows:
                        for row in full_rows:
                            del block_list[row]
                            block_list.insert(0, [''] * C)
                            score += 10  # 增加行消除得分
                            play_sound("row_clear")  # 行消除得分播放音效

            # 绘制游戏状态
            ed.fill_rect(OFFSET_X, OFFSET_Y, WIDTH, HEIGHT, COLORS['bg'])
            draw_borders()
            for r in range(R):
                for c in range(C):
                    if block_list[r][c]:
                        draw_cell(c, r, COLORS[block_list[r][c]])
            if current_block:
                draw_block(current_block)

            # 显示得分
            ed.text(f"分:{score}", 0, OFFSET_Y + 5, 0xFFFF)

            ed.show()
            time.sleep(0.3)  # 控制游戏速度

    # 初始化蜂鸣器
    play_sound("start_game")  # 游戏开始播放音效

    ed.fill(COLORS['bg'])
    game_loop()